--
-- Author:      name
-- DateTime:    2018-08-21 15:57:48
-- Description: 游戏主逻辑

local skynet = require "skynet"
local log = require "Log"
local config = require "configquery"
local Timer = require "timer"
local FSM = require "fsm"
local NodeMessage = require "NodeMessage"
local Universal = require "Universal"
local json = require "cjson"
require "common"
local Rule = require("rt_mingpaipinshi.Rule")


local mix_array = mix_array
local table_clone = table_clone
local floor = math.floor
local four_five = math.four_five
local random = math.random


local MachineBase = require "common.MachineBase"
local Machine = class("Machine",MachineBase)

function Machine:ctor(tableid,rule)
	json.encode_sparse_array(true)
	self.super:ctor(tableid,rule) --父类

	--状态时间
	self.stateTime = {	
		rest = 5,		--休息时间
		wait = 1,		--等待
		start = 4,		--开始
		bank = 15,		--抢庄
		bankok = 1,		--定庄
		bet = 15,		--开始(下注)
		leftcard = 15,	--剩余牌
		settlement = 8, --结算时间
	}
	
	--配置信息
	self.tbPlayerCard = {}
	self.tbPlayerBet = {}
	local sql = string.format("select * from private_tables where tableid = %d", self.tableid)
	local res = skynet.call("mysql_service", "lua", "execute", sql)
	self.table_config = res[1]
	self.table_config.table_rule_config = json.decode(self.table_config.setting)	
	self.bottomChip = self.table_config.table_rule_config.bottomChip
	self.tbBankRate = self.table_config.table_rule_config.bankRate.value
	self.tbBetRate = self.table_config.table_rule_config.betRate.value
	self.playerCount = self.table_config.table_rule_config.playerCount				--人数
	self.playCount = self.table_config.table_rule_config.play_count					--局数
	self.managerid = self.table_config.managerid				--局数
	self.tableCreateTime = self.table_config.create_time
	self.room_flag = ""..self.tableid..os.time()--大局唯一标识

	self.tableExistTime = 24 * 60 * 60	--牌桌持续时间

	local ruleArgs = {niuRate = self.table_config.table_rule_config.niuRate, 
					  specialCardRate = self.table_config.table_rule_config.specialCardRate}
	self.rule = Rule.new(ruleArgs)				
	
	self.trdid = 0	--当前牌桌玩了几局
	self.kickDoNothingNum = 2	--玩家几局未操作踢人
	self.maxSeatNum = 12

	self.tbTableStateValue = {	
						start = 1,
						bank = 2,
						bank_ok = 2,
						bet = 3,
						leftcard = 4,
						settlement = 5,
						rest = 6,
						wait = 7,
					}
	--状态
	--休息，开始玩家操作，抢庄, 下注，发牌，结算
	--state1 --eventName --state2 --callback
	self.gameStateTransitionTable = {
		{"rest", 		"to_start", 			"start", 		     function() self:onStart() end },
		{"rest", 		"to_wait", 				"wait", 		     function() self:onWait() end },
		{"wait", 		"to_start", 			"start", 		     function() self:onStart() end },
		{"start", 		"to_bank", 				"bank", 		     function() self:onBank() end },
		{"bank", 		"to_bank_ok", 			"bank_ok", 		     function() self:onBankOK() end },
		{"bank_ok", 	"to_bet",				"bet", 			     function() self:onBet() end },
		{"bet", 	    "to_leftcard",			"leftcard", 	     function() self:onLeftCard() end },
		{"leftcard", 	"to_settlement",		"settlement", 	     function() self:onSettlement() end },
		{"settlement", 	"to_rest", 				"rest", 		     function() self:onRest() end },
		{"settlement", 	"to_game_completed", 	"game_completed",    function() self:onGameCompleted() end },
	}
	--状态机
	self.fsm = FSM.new(self.gameStateTransitionTable)
	self:reset()
	self:checkActiveTableAndClose(30 * 60)
	self:timeoutCloseTable(24 * 60 * 60)
end

---------------------------------------------------------
-- private
---------------------------------------------------------

--override加入玩家
function Machine:addPlayer(player)
	player.playing = player.playing or false
	player.openCard = player.openCard or false
	player.doNothingNum = player.doNothingNum or 0
	player.alreadyPrepare = player.alreadyPrepare or false
	player.autoPrepare = player.autoPrepare or false
	if not self.player_list[player.playerid] then
		player.chip = 0
	end
	self.super.addPlayer(self, player)
end

--重置数据
function Machine:reset()
	self.rule:shuffle()
	self.tbRaceBankRate = {} --抢庄玩家列表
	self.tbPlayerCard = {}
	self.tbPlayerBet = {}
	self.record = {}
	self.bankData = {}
	self.operStartTime = os.time()

	for k, v in pairs(self.player_list) do
		v.openCard = false
		v.playing = false
		v.alreadyPrepare =false
	end
end

function Machine:onGameCompleted()
	self:ntGameCompleted()
	--删除房间
	local sql = string.format("delete from private_tables where tableid = %d;", self.tableid)
	skynet.send("mysql_service", "lua", "execute", sql)	 
	
	for k, v in pairs(self.player_list) do					
		if not self.player_list[k] then return end
		local sql = string.format("delete from user_online where uid = %d;", k)
		skynet.send("mysql_service", "lua", "execute", sql)
		self:sendGate(self.player_list[k], 'update_tableid', 0)
		self:sitUp(k)
		self.player_list[k] = nil		
	end
	self:updatePlayerNum()
	
	--退出
	self:exit()	
end

function Machine:removePlayerById(playerid, reason)
	if not self.player_list[playerid] then return end
	local sql = string.format("delete from user_online where uid = %d;", playerid)
    skynet.send("mysql_service", "lua", "execute", sql)
	local data = {nt_kick_table = {
		playerid = playerid,
		content = reason.content or "",
		kick_reason = reason.kick_reason or 0,
	}}
	self:sendMessage(playerid, data)
	self:sendGate(self.player_list[playerid], 'update_tableid', 0)
	self:sitUp(playerid)
	self.player_list[playerid] = nil
	self:updatePlayerNum()
end

function Machine:enterTable(playerid)
	self:ntNoSeatPlayerNum(playerid)
end

--离开桌子
function Machine:leaveTable(playerid)	
	if self.player_list[playerid].playing and
	   (not (self:getState() == "rest" or  self:getState() == "wait")) then
		AssertEx(false, 'leave_table_res', 9)
	end
	log.debug('玩家离开牌桌>>>>>>>>>>>',playerid,self.tableid)
	local res = self:sitUp(playerid)
	self:sendGate(self.player_list[playerid], 'update_tableid', 0)
	self.player_list[playerid] = nil
	self:updatePlayerNum()
	self:ntNoSeatPlayerNum()
	return res
end

--掉线处理
function Machine:disconnect(playerid)	
	local player = self.player_list[playerid]
	log.debug('玩家掉线>>>>>>>>>>>',playerid,self.tableid,player.playing,player.disconnect)
	--旁观者掉线马上踢出大厅
	player.estalished = false
	if not player.playing and player.disconnect then -- 在结算
		
		print("########在旁观玩家中直接踢走")	
		self:sendGate(player, 'update_tableid', 0)
		self:sitUp(playerid)
		self.player_list[playerid] = nil
		return true
	end	
	return false
end

function Machine:getPlayerInfo(playerid)
	local player = self.player_list[playerid]
	local playerInfo = {}
	if table.empty(player) then
		return {}
	end
	playerInfo.seatid = player.seatid 
	playerInfo.playerid = player.playerid 
	playerInfo.nick = player.nick 
	playerInfo.chip = player.chip 
	playerInfo.icon = player.icon 
	playerInfo.diamond = player.diamond 
	playerInfo.viplevel = player.viplevel 
	playerInfo.level = player.level
	playerInfo.sex = player.sex
	playerInfo.playing = player.playing
	playerInfo.already_prepare = player.alreadyPrepare
	playerInfo.auto_prepare = player.autoPrepare
	playerInfo.card_type = -1
	return playerInfo
end

--
function Machine:playerRaceBank(playerid, args)
	self.player_list[playerid].doNothingNum = 0
	if self:getState() ~= "bank" then
		AssertEx(false, "rt_mpps_race_bank_res", 47)
	end
	local player = self.player_list[playerid]
	if not player.playing or self.tbRaceBankRate[player.playerid] then
		AssertEx(false, "rt_mpps_race_bank_res", 50)
	end
	self.tbRaceBankRate[playerid] = args.rate
	local data = {rt_mpps_nt_sb_bank = {playerid = playerid, rate = args.rate}}
	self:sendToAll(data)

	local raceBankNum = 0 
    local playingNum = 0
    for k,v in pairs(self.player_list) do
    	if v.playing then
    		playingNum = playingNum + 1
			if self.tbRaceBankRate[k] then
				raceBankNum = raceBankNum + 1				
			end
		end
    end
    if playingNum > 0 and raceBankNum == playingNum then
    	local callback = function ()
			self.fsm:fire("to_bank_ok")
		end
		self:setTime(1, callback)
    end
end
	
---------------------------------------------------------
-- 状态
---------------------------------------------------------
function Machine:onWait()
	log.debug("_____________rt_mpps onWait")
	self.operStartTime = os.time()
	local callback = function ( ... )	
		if self:canStartGame() then	
			self.fsm:fire("to_start")	
		end						
	end
	self:setTime(self.stateTime.wait, callback)	
	self:ntWait()
end

--休息
function Machine:onRest()
	log.debug("_____________rt_mpps onRest")
	self.operStartTime = os.time()

	for k,v in pairs(self.player_list) do
		if v.playing then
			v.doNothingNum = v.doNothingNum +1
		end
	end

	--重置数据
	self:reset()
	self:ntRest()
	self:removeDisconnect()	
	
	for k, v in pairs(self.player_list) do
		if v.autoPrepare then
			self:prepareReq(k)
		end		
	end

	local callback = function ( ... )	
		if self:canStartGame() then
			self.fsm:fire("to_start")		
		else	
			self.fsm:fire("to_wait")	
		end			
	end
	self:setTime(self.stateTime.rest, callback)
end


--开始
function Machine:onStart()
	log.debug("_______rt_mpps onStart")		
	self.trdid = self.trdid + 1	
	if self.trdid == 1 then
		local sql = string.format("update private_tables set status=%d where tableid = %d;", 2, self.tableid)
		local res = skynet.send("mysql_service", "lua", "execute", sql)	
	end
	for k, v in pairs(self.player_list) do
		if v.alreadyPrepare or v.autoPrepare then 
			self.player_list[k].playing = true
		end
	end
	local tbPlayingid = self:getPlayingid()
	for k, v in pairs(tbPlayingid) do
		self.tbPlayerCard[v] = self.rule:getCard(4)
	end	
	self:ntStart()

	--开始下注
	self.operStartTime = os.time()	
	local callback = function ()
		--停止下注
		self.fsm:fire("to_bank")
	end
	self:setTime(self.stateTime.start, callback)
end

function Machine:onBank()
	log.debug("________________________________________rt_mpps onBank")
	local tbPlayingid = self:getPlayingid()
	self:ntBank()

	self.operStartTime = os.time()
	local callback = function ()
		self.fsm:fire("to_bank_ok")
	end
	self:setTime(self.stateTime.bank, callback)
end

function Machine:onBankOK()
	log.debug("______rt_mpps onBankOk", self.tbRaceBankRate)
	
	self.bankData = {}
	local tbRatePlayer = {}	
	local maxBankRate	--最大抢庄倍数
	for playerid, rate in pairs(self.tbRaceBankRate) do
		maxBankRate = maxBankRate or rate
		if maxBankRate < rate then
			maxBankRate = rate
		end
		tbRatePlayer[rate] = tbRatePlayer[rate] or  {}
		table.insert(tbRatePlayer[rate], playerid)
	end

	local allRate = {}
	for i=1, self.maxSeatNum do
		local playerid = self.seat_list[i]
		if not playerid then
			table.insert(allRate, -1)
		else
			table.insert(allRate, self.tbRaceBankRate[playerid] or 0)
		end
	end

	local data = {}
	if maxBankRate and maxBankRate > 0 then	--有人抢庄
		if #tbRatePlayer[maxBankRate] == 1 then
			local playerid = tbRatePlayer[maxBankRate][1]
			self.bankData = {rate = maxBankRate, playerid =playerid}
			data = {rt_mpps_nt_bank_ok = {playerid = playerid,
									 rate = self.bankData.rate, 
									 time = self.stateTime.bankok,
									 allrate = allRate }}
		elseif #tbRatePlayer[maxBankRate] > 1 then	--多人抢庄相同的倍数，随机
			local r = math.random(1, #tbRatePlayer[maxBankRate])		
			local num = table.size(tbRatePlayer[maxBankRate])	
			self.bankData = {rate = maxBankRate, playerid = tbRatePlayer[maxBankRate][r]}
			data = {rt_mpps_nt_random_bank_ok = {rate = self.bankData.rate, 
										    allrate = allRate, 
										    playerid = self.bankData.playerid,
										    time = self.stateTime.bankok + math.floor(num * 0.5),
										    arr_playerid = tbRatePlayer[maxBankRate]}}
		end
	else 				--没人抢庄，随机
		local tbPlayerid = self:getPlayingid()
		local r = math.random(1, #tbPlayerid)
		local num = table.size(tbPlayerid)
		self.bankData = {rate = 1, playerid = tbPlayerid[r]}
		data = {rt_mpps_nt_random_bank_ok = {rate = self.bankData.rate, 
										allrate = allRate,
										playerid = self.bankData.playerid,
										time = self.stateTime.bankok + math.floor(num * 0.5),
										arr_playerid = tbPlayerid}}
	end

	self.operStartTime = os.time()
	local callback = function ()
		self.fsm:fire("to_bet")
	end	
	if data.rt_mpps_nt_bank_ok then
		self:setTime(self.stateTime.bankok, callback)
	else
		self:setTime(data.rt_mpps_nt_random_bank_ok.time, callback)
	end
	print("bankok data:", data)
	self:sendToAll(data)
end

function Machine:onBet()
	log.debug("_____________rt_mpps onBet")
	self.operStartTime = os.time()
	self:ntBet()
	local callback = function ()
		self.fsm:fire("to_leftcard")
	end	
	self:setTime(self.stateTime.bet, callback)
end

--发剩余牌
function Machine:onLeftCard()
	log.debug("_____________rt_mpps onLeftCard")	
	local tbPlayingid = self:getPlayingid()
	for k, v in pairs(tbPlayingid) do
		if v ~= self.bankData.playerid then
			self.tbPlayerBet[v] = self.tbPlayerBet[v] or self.tbBetRate[1]
		end
		table.insert(self.tbPlayerCard[v], self.rule:getCard(1)[1])
	end	
	self:ntLeftCard()
	self.operStartTime = os.time()	
	local callback = function ()
		self.fsm:fire("to_settlement")
	end
	self:setTime(self.stateTime.leftcard, callback)
end

--结算
function Machine:onSettlement()
	log.debug("_____________rt_mpps onSettlement")
	
	--self:beforRecord()	
	local settlementData = {}
	local tbPlayerid= self:getPlayingid()
	local bankCard = self.tbPlayerCard[self.bankData.playerid]
	local bankNiuRes = self.rule:getNiu(bankCard)
	local bankCardType = self.rule:getCardType(bankNiuRes.weight)
	local bankWinChip = 0	
	--闲家
	for k, v in pairs(self.tbPlayerBet) do
		local player = self.player_list[k]
		if player.playing and self.bankData.playerid ~= player.playerid then
		    local bet = self.bottomChip * self.bankData.rate * v 
		    local playerNiuRes = self.rule:getNiu(self.tbPlayerCard[k])
		    local playerCardType = self.rule:getCardType(playerNiuRes.weight)
		    local playerSettlement = {playerid = player.playerid, cards = playerNiuRes.card, card_type = playerCardType}
		    if bankNiuRes.weight > playerNiuRes.weight then
		    	bankWinChip = bankWinChip + bet * self.rule:getRate(bankNiuRes.weight)
		    	playerSettlement.winChips = -bet * self.rule:getRate(bankNiuRes.weight)
		    else
		    	bankWinChip = bankWinChip - bet * self.rule:getRate(playerNiuRes.weight)
		    	playerSettlement.winChips = bet * self.rule:getRate(playerNiuRes.weight)
		    end
		    table.insert(settlementData, playerSettlement) 
		end
	end

	--庄家
	local bankSettlement = {}
	bankSettlement.cards = bankNiuRes.card
	bankSettlement.card_type = bankCardType
	bankSettlement.playerid = self.bankData.playerid

	bankSettlement.winChips = bankWinChip
	table.insert(settlementData, bankSettlement)
	
	for k, v in pairs(settlementData) do
		local player = self.player_list[v.playerid]
		player.chip = player.chip + v.winChips
		v.chip = player.chip
	end
	self:sendToAll({rt_mpps_nt_end = {player_settle = settlementData, time = self.stateTime.settlement}})	
	self.record.settlement = settlementData	

	self.operStartTime = os.time()			
	local callback = function ()
		--休息
		if self.trdid < self.playCount then
			self.fsm:fire("to_rest")
		else
			self.fsm:fire("to_game_completed")
		end
	end
	self:setTime(self.stateTime.settlement, callback)
	self:doRecord()
end

function Machine:beforRecord()
	self.record = {settlement = {}, beforeChip = {}}
	self.record.betRate = self.tbPlayerBet
	for k, v in pairs(self.player_list) do
		if v.playing then
			table.insert(self.record.beforeChip, {playerid = v.playerid, chip = v.chip})
		end
	end
end

function Machine:doRecord()
	self.record.bottomChip = self.bottomChip
	self.record.roomid = self.roomid
	self.record.bankData = self.bankData
	self.record.managerid = self.managerid
	local time = os.time()
	local tid = tonumber(string.sub(self.tableid, -6))
	local manager = self.player_list[self.managerid]
	local sql = string.format("insert into qclandlord_tablelog (tid, trdid, svid, tlcnt, tllog, tltime, game, gameid, gametype, room_owner, room_flag) \
														 values(%d,%d,%d,%d, '%s', %d,%d,%d,%d,%d, %s);",
		 tid, self.trdid, self.gameid, table.size(self.player_list), json.encode(self.record), time, manager.game or 0, self.gameid, self.roomid, self.managerid, self.room_flag)
	local res = skynet.call("mysql_log", "lua", "execute", sql)

	local tlid = res.insert_id
	for k, v in pairs(self.record.settlement) do
		local wlfold
		if v.playerid == self.bankData.playerid then
			wlfold = self.bankData.rate
		else
			wlfold = self.tbPlayerBet[v.playerid]
		end		
		local player = self.player_list[v.playerid]
		local wlleft = player.chip
		local wlwin = v.winChips
		local wlflag
		if wlwin > 0 then wlflag = 1 else wlflag = 0 end		

		local str1 = 'qclandlord_winlog' .. " (tlid, uid, pfid, usid, tid, room_id, svid, trdid, wlfold, wlleft, wlwin, wlflag, wltime, game, gameid, gametype)"
		local sql1 = string.format("insert into %s values(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d);", str1, tlid, v.playerid, player.pfid or 0, player.usid or 0, tid, self.roomid, 13,
														self.trdid, wlfold, wlleft, wlwin, wlflag, time, player.game or 0,self.gameid, self.roomid)
		local res = skynet.call("mysql_log", "lua", "execute", sql1)
		--print("-------------------------------->res sql1",res, sql1)
	end


end

--取桌子状态
function Machine:getTableStatus(playerid)
	local seatPlayers = {}
	for k, v in pairs(self.player_list) do
		if v.seatid and v.seatid > 0 then
			local seat = self:getPlayerInfo(k)
			seat.open_card = v.openCard
			seat.sex = v.sex
			seat.card_type = -1
			if self:getState() == "leftcard" and v.openCard 
			   or self:getState() == "settlement"
			   or playerid == v.playerid then

				seat.cards = self.tbPlayerCard[v.playerid]
				if self:getState() == "settlement" and v.playing then
					seat.open_card = true
					local cards = self.tbPlayerCard[v.playerid]
					local weight = self.rule:getNiu(self.tbPlayerCard[v.playerid]).weight
					seat.card_type = self.rule:getCardType(weight)
				end
			end
			if v.playing then			
				if self.bankData.playerid and self.bankData.playerid ~= v.playerid then
					seat.already_bet_rate = self.tbPlayerBet[v.playerid]
				end
				seat.already_bank_rate = self.tbRaceBankRate[v.playerid]
			end
			table.insert(seatPlayers, seat)
		end
	end
	local status = {		
		table_num = string.sub(self.tableid, -6),
		seat_player = seatPlayers,
		config = self:getConfig(),
		time = self:getOperTime(), --当前操作所剩余时间
		state = self.tbTableStateValue[self:getState()],
		playing = self.player_list[playerid].playing,
		bankerPlayerid = self.bankData.playerid,
		cur_round =self.trdid,
		managerid = self.managerid,
		noseat_num = self:getNoSeatPlayerNum(),
	    table_flag = self.room_flag
	}	

	log.debug("playerid:" ..playerid, "pinshi Table status ################",status)	
	return status
end

--请求下注
function Machine:onPlayerBet(playerid, args)
	local player = self.player_list[playerid]
	player.doNothingNum = 0
	if self:getState() ~= "bet" then
		AssertEx(false, "rt_mpps_bet_res", 32)
	end
	if args.rate > self:getMaxPlayerRate() then
		AssertEx(false, "rt_mpps_bet_res", 48)
	end
	
	if not player.playing or self.tbPlayerBet[player.playerid] then
		AssertEx(false, "rt_mpps_bet_res", 49)
	end
	
	if self.bankData.playerid == playerid then
		AssertEx(false, "ps_bet_res", 36)
	end

	if self.tbPlayerBet[playerid] then --已经下注
		return
	end	
	self.tbPlayerBet[playerid] = args.rate

	local data = {rt_mpps_nt_sb_bet = {playerid = playerid, rate = args.rate}}
    self:sendToAll(data)

    local betNum = 0 
    local playingNum = 0
    for k,v in pairs(self.player_list) do
    	if v.playing then
    		playingNum = playingNum + 1
			if self.tbPlayerBet[k] then
				betNum = betNum + 1				
			end
		end
    end
    if playingNum > 0 and betNum == playingNum - 1 then --全部下注了提前发剩余牌
    	local callback = function ()
			self.fsm:fire("to_leftcard")
		end
		self:setTime(1, callback)
    end

	return {}
end

--请求亮牌
function Machine:onOpenCard(playerid, args)
	if self:getState() ~= "leftcard" or self.player_list[playerid].openCard then
		return
	end
	self.player_list[playerid].openCard = true
	self.player_list[playerid].doNothingNum = 0
	local playerNiuRes = self.rule:getNiu(self.tbPlayerCard[playerid])
	local playerCardType = self.rule:getCardType(playerNiuRes.weight)	
	local data = {rt_mpps_nt_sb_open_card = {playerid = playerid, 
										seatid =self.player_list[playerid].seatid,
										cards = playerNiuRes.card,
										card_type = playerCardType,
										}}
    self:sendToAll(data)
    print("------------->onOpenCard", data)

    local openCardPlayingNum = 0 
    local playingNum = 0
    for k,v in pairs(self.player_list) do
    	if v.playing then
    		playingNum = playingNum + 1
			if v.openCard then
				openCardPlayingNum = openCardPlayingNum + 1				
			end
		end
    end
    if playingNum > 0 and openCardPlayingNum == playingNum then
    	local callback = function ()
			self.fsm:fire("to_settlement")
		end
		self:setTime(1, callback)
    end
	return {}
end

--坐下
function Machine:sitDown(playerid, seatid)
	local player = self.player_list[playerid]
	if player.playing and self:getState() ~= "rest" and self:getState() ~= "wait" then
		AssertEx(false, "sitdown_res", 1301)
	end
	if (not player.seatid) and table.size(self.seat_list) >= self.playerCount then
		AssertEx(false, "sitdown_res", 1302)
	end
	if (seadid and seadid > self.maxSeatNum and seadid <= 0) or self.seat_list[seatid]  then
		return
	end	
	if player.seatid then --在坐下先站起
		self:sitUp(playerid)
	end

	self.seat_list[seatid] = playerid
	player.seatid = seatid
	self:sitDownCallback(playerid)
	return seatid	
end


function Machine:sitUp(playerid)
	if not playerid or playerid <=0 then
		return false
	end	
	local player = self.player_list[playerid]
	if not player then
		return false
	end
	if player.playing and self:getState() ~= "rest" and self:getState() ~= "wait" then
		return false
	end

	local seatid = player.seatid
	self:sitUpCallback(seatid, playerid)
	if seatid then 
		self.seat_list[seatid] = nil		
	end
	player.seatid = nil	
	return true
end

--@override
function Machine:sitDownCallback(playerid)
	print("------------------------------------>sitDownCallback", playerid)
	local player = self:getPlayerInfo(playerid)
	local data = {rt_mpps_nt_seat_change = {
		seat_player = player,
		seat = true,
	}}	
	self:sendToAll(data)
	self:ntNoSeatPlayerNum()
end


--@override
function Machine:sitUpCallback(seatid, playerid)
	local player = self:getPlayerInfo(playerid)
	local data = {rt_mpps_nt_seat_change = {
		seat_player = player,
		seat = false,
	}}	
	self:sendToAll(data)
	self:ntNoSeatPlayerNum()
end

--有人准备
 function Machine:prepareReq(playerid)
 	if self:getState() ~= "wait" and self:getState() ~= "rest" then return end
 	local player = self.player_list[playerid]
 	if not player.seatid then
 		return
 	end
 	player.alreadyPrepare = true
 	skynet.fork( function ()
 		local data = { rt_mpps_nt_Prepare = {playerid = playerid} }
 		self:sendToAll(data)
 		if self:getState() == "wait" and self:getOperTime() <= 1 and self:canStartGame() then
 			self.fsm:fire("to_start")
 		end
 	end ) 	
 	return  {playerid = playerid}
 end

--自动准备
function Machine:autoPrepareReq(args)
	local player = self.player_list[args.playerid]
 	if not player.seatid then
 		return
 	end
 	player.autoPrepare = args.auto_prepare
	if args.auto_prepare then
		self:prepareReq(args.playerid)
	end	
	return {playerid = args.playerid, auto_prepare = args.auto_prepare}
end

--------------------------------------------------wait-----------------------------
-- 推送消息
-------------------------------------------------------------------------------
function Machine:ntStart()
	local tbPlayerid = {}
	for k, v in pairs(self.player_list) do
		local data = {rt_mpps_nt_start={
		cur_round = self.trdid,
 		time = self.stateTime.start, 
 		cards = self.tbPlayerCard[k],		
 		playingid_list = self:getPlayingid(), 		
		}}		
		self:sendMessage(k, data)
	end
	log.debug("__________rt_mpps_ntStart", data)
end

function Machine:ntWait()
	local data = {rt_mpps_nt_wait={
 		gamestatus = self.tbTableStateValue[self:getState()],	
	}}
	self:sendToAll(data)
end

function Machine:ntBank()
	local tbPlayingid = self:getPlayingid()
	for k, v in pairs(self.player_list) do
		local data = {rt_mpps_nt_bank = {
					time = self.stateTime.bank,
					}}
		self:sendMessage(k, data)
	end	
end

function Machine:ntBet()	
	for k, v in pairs(self.player_list) do	
		local data = {rt_mpps_nt_bet = {
					time = self.stateTime.bet,
					}}
		self:sendMessage(k, data)
	end	
end

function Machine:ntRest()
	self:reset()
	local data = {rt_mpps_nt_rest={
 		time = self.stateTime.rest
	}}
	print("_________rt_mpps_ntRest", data)
	self:sendToAll(data)	
end

function Machine:ntLeftCard()
	local tbPlayingid = self:getPlayingid()
	for k, v in pairs(self.player_list) do	
		local cards = {}
		if v.playing then
			cards = {self.tbPlayerCard[k][#self.tbPlayerCard[k]]}
		end
		local data = {rt_mpps_nt_left_card = {
					time = self.stateTime.leftcard,
					cards = cards
					}}
		self:sendMessage(k, data)
	end	
end

function Machine:ntGameCompleted()
	local tid = tonumber(string.sub(self.tableid, -6))
	local sql = string.format("select from qclandlord_winlog where tid = %d;", tid)
	local sqlRes = skynet.call("mysql_service", "lua", "execute", sql)
	print("--------------------sqlRes", sqlRes)
	local data = {rt_mpps_nt_game_completed={
	}}
	print("_________rt_mpps_ntGameCompleted", data)
	self:sendToAll(data)
end
----------------------------------
-- 数据操作
----------------------------------
--状态对应的数字
function Machine:getStateNum()
	local state = self:getState()
	for k, v in pairs(self.gameStateTransitionTable) do 
		if state == v[1] then 
			return k
		end
	end
	return 
end

--桌子相关配置
function Machine:getConfig()
	local bank_rate = self.tbBankRate
	local bet_rate = self.tbBetRate
	return {setting = self.table_config.setting}
end

--正在玩的
function Machine:getPlayingid()
	local tbPlayerid = {}
	for k, v in pairs(self.player_list) do
		if v.playing then
			table.insert(tbPlayerid, v.playerid)
		end
	end
	return tbPlayerid
end

--闲家下注最高倍数
function Machine:getMaxPlayerRate()
	local bet_rate  = self.tbBetRate
	return bet_rate[#bet_rate]
end

--给所有在线玩家发消息
function Machine:sendToAll(data)
	local playerList = {}	
	for k,v in pairs(self.player_list) do 
		if not v.disconnect and v.estalished  then 
			table.insert(playerList,k)
		end
	end
	if next(playerList) then
		self.nodeMessage:broadcastAllGate(playerList, data)
	end
end

function Machine:canStartGame()
	local prepareNum = 0
	for k, v in pairs(self.player_list) do
		if v.seatid and (v.alreadyPrepare or v.autoPrepare) then
			prepareNum = prepareNum + 1
		end
	end
	return prepareNum >= 2
end

function Machine:getCostFanka()
	local sql = string.format("select * from common_room where gameid = %d", self.gameid)
	local res = skynet.call("mysql_service", "lua", "execute", sql)
	local server_config = res[1].server_config
	if server_config then
		local price = json.decode(server_config).price
		for k,v in pairs(price or  {}) do
			if v.play_count == self.playCount then
				return v.cost or 0
			end
		end	
	end
	return 0
end

function Machine:closeTable(reason)
	--删除房间
	local sql = string.format("delete from private_tables where tableid = %d;", self.tableid)
	skynet.send("mysql_service", "lua", "execute", sql)	 
	--踢人
	for k, v in pairs(self.player_list) do					
		self:removePlayerById(k, reason)
	end
	--退出
	self:exit()	
end

--房主解散房间
function Machine:onClosePrivateReq(playerid)
	if playerid ~= self.managerid or self.trdid > 0 then return false end
	--返还房卡
	local sql = string.format("update usergame set room_ticket=room_ticket + %d where uid=%d", self:getCostFanka(), self.managerid)		
	self.nodeMessage:sendService("mysql_service","execute", sql)
	local reason = {content = "房主了解散房间", kick_reason = 6}
	self:closeTable(reason)
	return true
end

--一定时间还未开始游戏，解散房间
function Machine:checkActiveTableAndClose(time)
	skynet.timeout(time * 100, function ( ... )
		if self.trdid == 0 then
			--返还房卡
			local sql = string.format("update usergame set room_ticket=room_ticket + %d where uid=%d", self:getCostFanka(), self.managerid)		
			self.nodeMessage:sendService("mysql_service","execute", sql)	

			local reason = {content = "长时间没开始游戏，解散房间并退还房卡", kick_reason = 5}
			self:closeTable(reason)
		end
	end)
end

--牌局时间到了结束退游戏
function Machine:timeoutCloseTable(time)
	skynet.timeout(time * 100, function ()
			local maxDelay = 3000
			local delay = 0
			local function _callback( ... )
				if self:getState() == "rest" or self:getState() == "wait" or self:getState() == "settlement" or delay > maxDelay then
					local reason = {content = "牌局时间结束", kick_reason =7}
					self:closeTable(reason)
					self.timer:unregister(self.closeHandler)
				else
					delay = delay + 1
				end
			end 		
			self.closeHandler = self.timer:register(1 , nil, _callback,true)
	end)
end

function Machine:ntNoSeatPlayerNum(playerid)
	local num = self:getNoSeatPlayerNum()
	local data = {rt_mpps_nt_no_seat_player_num = {
 					standPlayerNum = num}}
 	if playerid then
 		self:sendToOther(playerid, data)
 	else
 		self:sendToAll(data)
 	end	
end

--桌子人数
function Machine:getNoSeatPlayerNum()
	local num = 0
	for k,v in pairs(self.player_list) do
		if not v.seatid then
			num = num + 1 	
		end
	end
	return num
end

function Machine:getNoSeatPlayerList()
	local noSeatPlayerList = {}
	for k, v in pairs(self.player_list) do
		if not v.seatid then
			local seat = self:getPlayerInfo(k)
			table.insert(noSeatPlayerList, seat)
		end
	end
	return {rt_mpps_no_seat_player_list_res = {no_seat_player_list= noSeatPlayerList}}
end
----------------------------------------------------------------------------------------------
---------开始游戏
---------------------------------------------------------------------------------------------- 
function Machine:start()
	self.fsm:set("rest")
	self.fsm:fire("to_wait")
end

return Machine